Bibiografia da Aula
Livro R4DS Wickham e Grolemund, cap 13.
Tidy explain Garrick Aden-Buie disponível em https://github.com/gadenbuie/tidyexplain
É raro ocorrer um trabalho de análise de dados usando apenas uma tabela, pois geralmente tem-se um conjunto de dados espalhado por diversas tabelas, por este motivo para responder às questões de interesse é necessário relaciona-las. Assim, coletivamente, multiplas tabelas de dados são chamadas de dados relacionais, por que geralmente o que importa são as relações e não os conjuntos de dados individuais.
As relações são sempre definidas entre um par de tabelas. Todas as outras relações são construídas a partir de uma premissa: as relações de três ou mais tabelas são sempre uma propriedade das relações entre cada par. Em alguns casos dois elemntos de um par podem ser a mesma tabela!Isso é necessário, por exemplo, se houver uma tabela com pessoas e cada pessoa é referenciada a seus pais.
Existem três famílias de verbos para trabalhar com dados relacionais.
Mutating joins, permitem que você combine variáveis de duas tabelas. Primeiro relaciona observaações por suas chaves, e então copia as variáveis de uma tabela para outra.
Filtering Joins, filtra observações de um data frame a partir da coincidência das mesmas em outro conjunto de dados.
Set operations, trata as observações como elementos fixos.
Vamos explorar os dados relacionais de nycflights13 usando os verbos para duas tabelas do dplyr.
library(tidyverse)
library(nycflights13)
Vamos usar o pacote nycflights13 para aprender sobre dados relacionais. nycflights13 contêm quatro tibbles relacionados ao dataframe flights.
airlines
## # A tibble: 16 x 2
## carrier name
## <chr> <chr>
## 1 9E Endeavor Air Inc.
## 2 AA American Airlines Inc.
## 3 AS Alaska Airlines Inc.
## 4 B6 JetBlue Airways
## 5 DL Delta Air Lines Inc.
## 6 EV ExpressJet Airlines Inc.
## 7 F9 Frontier Airlines Inc.
## 8 FL AirTran Airways Corporation
## 9 HA Hawaiian Airlines Inc.
## 10 MQ Envoy Air
## 11 OO SkyWest Airlines Inc.
## 12 UA United Air Lines Inc.
## 13 US US Airways Inc.
## 14 VX Virgin America
## 15 WN Southwest Airlines Co.
## 16 YV Mesa Airlines Inc.
airports
## # A tibble: 1,458 x 8
## faa name lat lon alt tz dst tzone
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
## 1 04G Lansdowne Airport 41.1 -80.6 1044 -5 A America/New_Yo~
## 2 06A Moton Field Municipal A~ 32.5 -85.7 264 -6 A America/Chicago
## 3 06C Schaumburg Regional 42.0 -88.1 801 -6 A America/Chicago
## 4 06N Randall Airport 41.4 -74.4 523 -5 A America/New_Yo~
## 5 09J Jekyll Island Airport 31.1 -81.4 11 -5 A America/New_Yo~
## 6 0A9 Elizabethton Municipal ~ 36.4 -82.2 1593 -5 A America/New_Yo~
## 7 0G6 Williams County Airport 41.5 -84.5 730 -5 A America/New_Yo~
## 8 0G7 Finger Lakes Regional A~ 42.9 -76.8 492 -5 A America/New_Yo~
## 9 0P2 Shoestring Aviation Air~ 39.8 -76.6 1000 -5 U America/New_Yo~
## 10 0S9 Jefferson County Intl 48.1 -123. 108 -8 A America/Los_An~
## # ... with 1,448 more rows
planes
## # A tibble: 3,322 x 9
## tailnum year type manufacturer model engines seats speed engine
## <chr> <int> <chr> <chr> <chr> <int> <int> <int> <chr>
## 1 N10156 2004 Fixed wing m~ EMBRAER EMB-1~ 2 55 NA Turbo-~
## 2 N102UW 1998 Fixed wing m~ AIRBUS INDUST~ A320-~ 2 182 NA Turbo-~
## 3 N103US 1999 Fixed wing m~ AIRBUS INDUST~ A320-~ 2 182 NA Turbo-~
## 4 N104UW 1999 Fixed wing m~ AIRBUS INDUST~ A320-~ 2 182 NA Turbo-~
## 5 N10575 2002 Fixed wing m~ EMBRAER EMB-1~ 2 55 NA Turbo-~
## 6 N105UW 1999 Fixed wing m~ AIRBUS INDUST~ A320-~ 2 182 NA Turbo-~
## 7 N107US 1999 Fixed wing m~ AIRBUS INDUST~ A320-~ 2 182 NA Turbo-~
## 8 N108UW 1999 Fixed wing m~ AIRBUS INDUST~ A320-~ 2 182 NA Turbo-~
## 9 N109UW 1999 Fixed wing m~ AIRBUS INDUST~ A320-~ 2 182 NA Turbo-~
## 10 N110UW 1999 Fixed wing m~ AIRBUS INDUST~ A320-~ 2 182 NA Turbo-~
## # ... with 3,312 more rows
weather
## # A tibble: 26,115 x 15
## origin year month day hour temp dewp humid wind_dir wind_speed
## <chr> <int> <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 EWR 2013 1 1 1 39.0 26.1 59.4 270 10.4
## 2 EWR 2013 1 1 2 39.0 27.0 61.6 250 8.06
## 3 EWR 2013 1 1 3 39.0 28.0 64.4 240 11.5
## 4 EWR 2013 1 1 4 39.9 28.0 62.2 250 12.7
## 5 EWR 2013 1 1 5 39.0 28.0 64.4 260 12.7
## 6 EWR 2013 1 1 6 37.9 28.0 67.2 240 11.5
## 7 EWR 2013 1 1 7 39.0 28.0 64.4 240 15.0
## 8 EWR 2013 1 1 8 39.9 28.0 62.2 250 10.4
## 9 EWR 2013 1 1 9 39.9 28.0 62.2 260 15.0
## 10 EWR 2013 1 1 10 41 28.0 59.6 260 13.8
## # ... with 26,105 more rows, and 5 more variables: wind_gust <dbl>,
## # precip <dbl>, pressure <dbl>, visib <dbl>, time_hour <dttm>
A partir do gráfico abaixo é possível verificar as relações entre cada tabela.
Para nycflights13:
flights se conectam a planes através de uma única variável, tailnum.
flights se conecta a airlines pela vaariável carrier
flights se conecta a airports de duas maneiras: pelas variáveis origin e dest
flights se conecta a weather através de origin (o lugar), year, month, day e hour.
1 - Imagine que você gostaria de traçar(aproximadamente)a rota que cada avião faz de sua origem até seu destino. Quais variáveis você precisaria usar? Quais variáveis você precisaria combinar?
2 - Me esqueci de desenhar a relação entre weather e airports. Qual e a relação e como ela deveria aparecer no diagrama mostrado anteriormente?
3 - weather contêm apenas informações dos aeroportos de origem (NYC). Se o dataframe também tivesse dados sobre todos os aeorportos dos USA, que relação adicional esta tabela teria com flights?
4 - Sabemos que alguns dias do ano são “especiais”, que menos vôos ocorrem nesses dias. Como você representaria estes dados em um data frame? Quais seriam as chaves primárias desta tabela? Como ela se conectaria com as tabela existentes?
As variáveis usadas para conectar cada par de tabelas são chamadas de keys ou chaves. Uma chave é uma variável (ou conjunto de variáveis) que identifica unicamente uma observação.
Existem dois tipos de chaves:
Chave primária(primary key): identifica uma observação única em sua própria tabela. Por exemplo, planes$tailnum é uma chave primária porque identifica unicamente cada avião na tabela planes.
Foreign Key: Identifica uma observação única em outra tabela. Por exemplo, flights$tailnum é uma Foreign Key porque apareça na tabela flights onde relaciona cada vôo a a um avião único.
Uma variável também pode ser os dois tipos de chave ao mesmo tempo. Por exemplo, origin é parte da chave primária de weather e tambem é foreign key da tabela airport.
Uma vez que você tenha identificado as chaves primárias em suas tabelas, é boa prática verificar se elas realmente identificam unicamente cada observação. Podemos fazer isso com count(), contando as chaves primárias e procurando por entradas onde n é maior que um:
planes %>%
count(tailnum) %>%
filter(n > 1)
## # A tibble: 0 x 2
## # ... with 2 variables: tailnum <chr>, n <int>
weather %>%
count(year, month, day, hour, origin) %>%
filter(n > 1)
## # A tibble: 3 x 6
## year month day hour origin n
## <int> <int> <int> <int> <chr> <int>
## 1 2013 11 3 1 EWR 2
## 2 2013 11 3 1 JFK 2
## 3 2013 11 3 1 LGA 2
Pode acontecer de uma tabela não possuir uma chave primária explicita: cada linha é uma observação, mas nenhuma combinação de variáveis a identifica de forma confiável. Por exeplo, qual é a chave primária na tabela flights? Você pode pensar que seria a data mais o número do vôo ou tail number(número da cauda), mas nenhuma das duas é única.
flights %>%
count(year, month, day, flight) %>%
filter(n > 1)
## # A tibble: 29,768 x 5
## year month day flight n
## <int> <int> <int> <int> <int>
## 1 2013 1 1 1 2
## 2 2013 1 1 3 2
## 3 2013 1 1 4 2
## 4 2013 1 1 11 3
## 5 2013 1 1 15 2
## 6 2013 1 1 21 2
## 7 2013 1 1 27 4
## 8 2013 1 1 31 2
## 9 2013 1 1 32 2
## 10 2013 1 1 35 2
## # ... with 29,758 more rows
flights %>%
count(year, month, day, tailnum) %>%
filter(n > 1)
## # A tibble: 64,928 x 5
## year month day tailnum n
## <int> <int> <int> <chr> <int>
## 1 2013 1 1 N0EGMQ 2
## 2 2013 1 1 N11189 2
## 3 2013 1 1 N11536 2
## 4 2013 1 1 N11544 3
## 5 2013 1 1 N11551 2
## 6 2013 1 1 N12540 2
## 7 2013 1 1 N12567 2
## 8 2013 1 1 N13123 2
## 9 2013 1 1 N13538 3
## 10 2013 1 1 N13566 3
## # ... with 64,918 more rows
Se uma tabela não possui uma chave primária, pode ser bom criar uma com as funções mutate() e row_number(). Assim fica mais fácil relacionar observações se os dados foram filtrados é você quer verificar novamente os dados originais. Este tipo de chave é chamada de surrogate key.
Uma chave primária e sua correspondente foreign key em outra tabela formam uma realação. Relações são geralmente de um para muitos. Por exemplo,
1 - Faça uma chave surrogate para a tabela flights
2 - Identifique as chaves nos seguintes conjuntos de dados:
(talvez seja necessário instalar alguns pacotes e ler a documentação)
3 - Faça um diagrama ilustrando as conexões entre as tabelas Batting, Master, e Salaries no pacote Lahman. Faça outro diagrama que deve mostrar as relações entre Master, Managers, AwardsManagers.
Como você caracterizaria a relação entre as tabelas Batting, Pitching e Fielding.
Como o mutate(), as funções join adicionam variáveis a direita, então, se houverem muitas variáveis na tabela elas não aparecerão printadas, por este motivo iremos estreitar as tabelas dos próximos exemplos, criando tabelas menos largas(com menos colunas)
flights2 <- flights %>%
select(year:day, hour, origin, dest, tailnum, carrier)
flights2
## # A tibble: 336,776 x 8
## year month day hour origin dest tailnum carrier
## <int> <int> <int> <dbl> <chr> <chr> <chr> <chr>
## 1 2013 1 1 5 EWR IAH N14228 UA
## 2 2013 1 1 5 LGA IAH N24211 UA
## 3 2013 1 1 5 JFK MIA N619AA AA
## 4 2013 1 1 5 JFK BQN N804JB B6
## 5 2013 1 1 6 LGA ATL N668DN DL
## 6 2013 1 1 5 EWR ORD N39463 UA
## 7 2013 1 1 6 EWR FLL N516JB B6
## 8 2013 1 1 6 LGA IAD N829AS EV
## 9 2013 1 1 6 JFK MCO N593JB B6
## 10 2013 1 1 6 LGA ORD N3ALAA AA
## # ... with 336,766 more rows
(Lembre-se, no RStudio é possível usar _view() para evitar este tipo de problema.)
Imagine que você queira adicionar os nomes de linhas aéreas à tabela flights2. Você pode combinar as tabelas flights e Flights2 com um left_join():
flights2 %>%
select(-origin, -dest) %>%
left_join(airlines, by = "carrier")
## # A tibble: 336,776 x 7
## year month day hour tailnum carrier name
## <int> <int> <int> <dbl> <chr> <chr> <chr>
## 1 2013 1 1 5 N14228 UA United Air Lines Inc.
## 2 2013 1 1 5 N24211 UA United Air Lines Inc.
## 3 2013 1 1 5 N619AA AA American Airlines Inc.
## 4 2013 1 1 5 N804JB B6 JetBlue Airways
## 5 2013 1 1 6 N668DN DL Delta Air Lines Inc.
## 6 2013 1 1 5 N39463 UA United Air Lines Inc.
## 7 2013 1 1 6 N516JB B6 JetBlue Airways
## 8 2013 1 1 6 N829AS EV ExpressJet Airlines Inc.
## 9 2013 1 1 6 N593JB B6 JetBlue Airways
## 10 2013 1 1 6 N3ALAA AA American Airlines Inc.
## # ... with 336,766 more rows
Como resultado desta junção temos uma nova variável, name. Por este motivo chamamos este tipo de join de mutating join. Neste caso, seria possível ter o mesmo resultado usando a função mutate().
flights2 %>%
select(-origin, -dest) %>%
mutate(name = airlines$name[match(carrier, airlines$carrier)])
## # A tibble: 336,776 x 7
## year month day hour tailnum carrier name
## <int> <int> <int> <dbl> <chr> <chr> <chr>
## 1 2013 1 1 5 N14228 UA United Air Lines Inc.
## 2 2013 1 1 5 N24211 UA United Air Lines Inc.
## 3 2013 1 1 5 N619AA AA American Airlines Inc.
## 4 2013 1 1 5 N804JB B6 JetBlue Airways
## 5 2013 1 1 6 N668DN DL Delta Air Lines Inc.
## 6 2013 1 1 5 N39463 UA United Air Lines Inc.
## 7 2013 1 1 6 N516JB B6 JetBlue Airways
## 8 2013 1 1 6 N829AS EV ExpressJet Airlines Inc.
## 9 2013 1 1 6 N593JB B6 JetBlue Airways
## 10 2013 1 1 6 N3ALAA AA American Airlines Inc.
## # ... with 336,766 more rows
Entretanto, este método não é prático quando se precisa relacionar muitas variáveis, além de necessitar de uma leitura mais minunciosa para o seu entendimento.
Será mais fácil entender como funcionam os joins com uma representação visual de seu funcionamento:
#x
#> # A tibble: 3 x 2
#> id x
#> <int> <chr>
#> 1 1 x1
#> 2 2 x2
#> 3 3 x3
#y
#> # A tibble: 3 x 2
#> id y
#> <int> <chr>
#> 1 1 y1
#> 2 2 y2
#> 3 4 y4
As colunas coloridas representam a variável “chave”: usadas para relacionas as linhas(observações) entre as duas tabelas. A coluna cinza representa os valores.
Um join é uma maneira de conectar cada linha em x a zero, uma ou mais linhas em Y. Será possível entender melhor este funcionamento nas tabelas animadas que serão mostradas nos próximos exemplos.
É o tipo mais simples de Join, relaciona pares de observações quando suas chaves são iguais.
#inner_join(x, y, by = "id")
#> # A tibble: 2 x 3
#> id x y
#> <int> <chr> <chr>
#> 1 1 x1 y1
#> 2 2 x2 y2
As observações não relacionadas são ignoradas no output. Não se costuma usar este tipo de join em análises pois facilita a perda de observações.
Preserva observações que aparecem em pelo menos uma das tabelas, existem três tipos:
O join mais usado é o left join, você pode trazer dados de outra tabela preservando as observações originais.
Outra maneira de representar os joins é através de um diagrama de Venn:
Fonte: Hickham e Grolemund - Relational data
Até agora, em todos os diagramas assumimos que as chaves eram únicas, porém, não é sempre o caso. Agora vamos entender o que acontece quando as chaves não são únicas. Existem duas possibilidades:
1 - Uma das tabelas tem chaves duplicadas. isso acontece quando se quer adicionar informações adicionais, assim cria-se uma relação de um para muitos.
Fonte: Hickham e Grolemund - Relational data
x <- tribble(
~key, ~val_x,
1, "x1",
2, "x2",
2, "x3",
1, "x4"
)
y <- tribble(
~key, ~val_y,
1, "y1",
2, "y2"
)
left_join(x, y, by = "key")
## # A tibble: 4 x 3
## key val_x val_y
## <dbl> <chr> <chr>
## 1 1 x1 y1
## 2 2 x2 y2
## 3 2 x3 y2
## 4 1 x4 y1
2 - Existem chaves duplicadas nas duas tabelas. Isto geralmente é um erro porque em nenhuma das duas tabelas as chaves identificam de forma única uma observação.
Fonte: Hickham e Grolemund - Relational data
x <- tribble(
~key, ~val_x,
1, "x1",
2, "x2",
2, "x3",
3, "x4"
)
y <- tribble(
~key, ~val_y,
1, "y1",
2, "y2",
2, "y3",
3, "y4"
)
left_join(x, y, by = "key")
## # A tibble: 6 x 3
## key val_x val_y
## <dbl> <chr> <chr>
## 1 1 x1 y1
## 2 2 x2 y2
## 3 2 x2 y3
## 4 2 x3 y2
## 5 2 x3 y3
## 6 3 x4 y4
Até agora, os pares de tabelas foram sempre unidas por uma única variável e essa variável tem o mesmo nome nas duas tambelas. Esta restrição foi codificada por by=“key” . É possível usar outros valores para by para conectar tabelas de outras maneiras:
flights2 %>%
left_join(weather)
## Joining, by = c("year", "month", "day", "hour", "origin")
## # A tibble: 336,776 x 18
## year month day hour origin dest tailnum carrier temp dewp humid
## <int> <int> <int> <dbl> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
## 1 2013 1 1 5 EWR IAH N14228 UA 39.0 28.0 64.4
## 2 2013 1 1 5 LGA IAH N24211 UA 39.9 25.0 54.8
## 3 2013 1 1 5 JFK MIA N619AA AA 39.0 27.0 61.6
## 4 2013 1 1 5 JFK BQN N804JB B6 39.0 27.0 61.6
## 5 2013 1 1 6 LGA ATL N668DN DL 39.9 25.0 54.8
## 6 2013 1 1 5 EWR ORD N39463 UA 39.0 28.0 64.4
## 7 2013 1 1 6 EWR FLL N516JB B6 37.9 28.0 67.2
## 8 2013 1 1 6 LGA IAD N829AS EV 39.9 25.0 54.8
## 9 2013 1 1 6 JFK MCO N593JB B6 37.9 27.0 64.3
## 10 2013 1 1 6 LGA ORD N3ALAA AA 39.9 25.0 54.8
## # ... with 336,766 more rows, and 7 more variables: wind_dir <dbl>,
## # wind_speed <dbl>, wind_gust <dbl>, precip <dbl>, pressure <dbl>,
## # visib <dbl>, time_hour <dttm>
flights2 %>%
left_join(planes, by = "tailnum")
## # A tibble: 336,776 x 16
## year.x month day hour origin dest tailnum carrier year.y type
## <int> <int> <int> <dbl> <chr> <chr> <chr> <chr> <int> <chr>
## 1 2013 1 1 5 EWR IAH N14228 UA 1999 Fixe~
## 2 2013 1 1 5 LGA IAH N24211 UA 1998 Fixe~
## 3 2013 1 1 5 JFK MIA N619AA AA 1990 Fixe~
## 4 2013 1 1 5 JFK BQN N804JB B6 2012 Fixe~
## 5 2013 1 1 6 LGA ATL N668DN DL 1991 Fixe~
## 6 2013 1 1 5 EWR ORD N39463 UA 2012 Fixe~
## 7 2013 1 1 6 EWR FLL N516JB B6 2000 Fixe~
## 8 2013 1 1 6 LGA IAD N829AS EV 1998 Fixe~
## 9 2013 1 1 6 JFK MCO N593JB B6 2004 Fixe~
## 10 2013 1 1 6 LGA ORD N3ALAA AA NA <NA>
## # ... with 336,766 more rows, and 6 more variables: manufacturer <chr>,
## # model <chr>, engines <int>, seats <int>, speed <int>, engine <chr>
Por exemplo, se quisermos desenhar um mapa precisamos combinar os dados de flights e airports que contem a localização de cada aeroporto. Cada vôo tem uma origem e um destino airport, então precisamos especificar qual queremos unir a qual.
flights2 %>%
left_join(airports, c("dest" = "faa"))
## # A tibble: 336,776 x 15
## year month day hour origin dest tailnum carrier name lat lon alt
## <int> <int> <int> <dbl> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
## 1 2013 1 1 5 EWR IAH N14228 UA Geor~ 30.0 -95.3 97
## 2 2013 1 1 5 LGA IAH N24211 UA Geor~ 30.0 -95.3 97
## 3 2013 1 1 5 JFK MIA N619AA AA Miam~ 25.8 -80.3 8
## 4 2013 1 1 5 JFK BQN N804JB B6 <NA> NA NA NA
## 5 2013 1 1 6 LGA ATL N668DN DL Hart~ 33.6 -84.4 1026
## 6 2013 1 1 5 EWR ORD N39463 UA Chic~ 42.0 -87.9 668
## 7 2013 1 1 6 EWR FLL N516JB B6 Fort~ 26.1 -80.2 9
## 8 2013 1 1 6 LGA IAD N829AS EV Wash~ 38.9 -77.5 313
## 9 2013 1 1 6 JFK MCO N593JB B6 Orla~ 28.4 -81.3 96
## 10 2013 1 1 6 LGA ORD N3ALAA AA Chic~ 42.0 -87.9 668
## # ... with 336,766 more rows, and 3 more variables: tz <dbl>, dst <chr>,
## # tzone <chr>
flights2 %>%
left_join(airports, c("origin" = "faa"))
## # A tibble: 336,776 x 15
## year month day hour origin dest tailnum carrier name lat lon alt
## <int> <int> <int> <dbl> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
## 1 2013 1 1 5 EWR IAH N14228 UA Newa~ 40.7 -74.2 18
## 2 2013 1 1 5 LGA IAH N24211 UA La G~ 40.8 -73.9 22
## 3 2013 1 1 5 JFK MIA N619AA AA John~ 40.6 -73.8 13
## 4 2013 1 1 5 JFK BQN N804JB B6 John~ 40.6 -73.8 13
## 5 2013 1 1 6 LGA ATL N668DN DL La G~ 40.8 -73.9 22
## 6 2013 1 1 5 EWR ORD N39463 UA Newa~ 40.7 -74.2 18
## 7 2013 1 1 6 EWR FLL N516JB B6 Newa~ 40.7 -74.2 18
## 8 2013 1 1 6 LGA IAD N829AS EV La G~ 40.8 -73.9 22
## 9 2013 1 1 6 JFK MCO N593JB B6 John~ 40.6 -73.8 13
## 10 2013 1 1 6 LGA ORD N3ALAA AA La G~ 40.8 -73.9 22
## # ... with 336,766 more rows, and 3 more variables: tz <dbl>, dst <chr>,
## # tzone <chr>
1 - Compute o atraso médio por destino, então una aos dados da tabela airports, assim você poderá mostrar a distribuição espacial dos atrasos. Aqui esta um modo fácil de plotar um mapa dos estados unidos.
airports %>%
semi_join(flights, c("faa" = "dest")) %>%
ggplot(aes(lon, lat)) +
borders("state") +
geom_point() +
coord_quickmap()
Voce talvez queira usar size ou color dos pontos para mostrar o atraso médio em cada aeroporto.
2 - Adicione a localização da origem e do destino a tabela flights
3 - Existe relação entre a idade do avião e seus atrasos?
4 - Que condições climáticas influenciam nos atrasos?
5 -O que aconteceu em 13 de junho de 2013? Mostre o padrão espacial de atrasos, use o google para fazer uma referência crusada com o clima no dia.
Filtering joins relacionam observações do mesmo modo que muatating joins, mas afetam as observações, não as variáveis. Existem 2 tipos.
#semi_join(x, y, by = "id")
#> # A tibble: 2 x 2
#> id x
#> <int> <chr>
#> 1 1 x1
#> 2 2 x2
#anti_join(x, y, by = "id")
#> # A tibble: 1 x 2
#> id x
#> <int> <chr>
#> 1 3 x3
Semi-joins são úteis ao relacionar tabelas de sumário filtradas de volta para as linhas originais. Por exemplo, imagine que você encontrou os 10 destinos mais populares:
top_dest <- flights %>%
count(dest, sort = TRUE) %>%
head(10)
top_dest
## # A tibble: 10 x 2
## dest n
## <chr> <int>
## 1 ORD 17283
## 2 ATL 17215
## 3 LAX 16174
## 4 BOS 15508
## 5 MCO 14082
## 6 CLT 14064
## 7 SFO 13331
## 8 FLL 12055
## 9 MIA 11728
## 10 DCA 9705
Agora você quer encontrar cada vôo que foi para cada um destes destinos. Você poderia fazer um filtro:
flights %>%
filter(dest %in% top_dest$dest)
## # A tibble: 141,145 x 19
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 1 1 542 540 2 923 850
## 2 2013 1 1 554 600 -6 812 837
## 3 2013 1 1 554 558 -4 740 728
## 4 2013 1 1 555 600 -5 913 854
## 5 2013 1 1 557 600 -3 838 846
## 6 2013 1 1 558 600 -2 753 745
## 7 2013 1 1 558 600 -2 924 917
## 8 2013 1 1 558 600 -2 923 937
## 9 2013 1 1 559 559 0 702 706
## 10 2013 1 1 600 600 0 851 858
## # ... with 141,135 more rows, and 11 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
Mas é difícil fazer o mesmo para múltiplas variáveis. Por exemplo, imagine que você encontrou os 10 dias com maiores atrasos médios. Como você construiria um filtro que usasse year, month e day para relacionar a de volta a tabela flights?
Ao invés disso você pode usar um semi-join, que conecta as duas tabelas como um mutating join, mas ao invés de adicionar novas colunas, mantem apenas as colunas de x que tem uma correspondência em y.
y
flights %>%
semi_join(top_dest)
## Joining, by = "dest"
## # A tibble: 141,145 x 19
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
## <int> <int> <int> <int> <int> <dbl> <int> <int>
## 1 2013 1 1 542 540 2 923 850
## 2 2013 1 1 554 600 -6 812 837
## 3 2013 1 1 554 558 -4 740 728
## 4 2013 1 1 555 600 -5 913 854
## 5 2013 1 1 557 600 -3 838 846
## 6 2013 1 1 558 600 -2 753 745
## 7 2013 1 1 558 600 -2 924 917
## 8 2013 1 1 558 600 -2 923 937
## 9 2013 1 1 559 559 0 702 706
## 10 2013 1 1 600 600 0 851 858
## # ... with 141,135 more rows, and 11 more variables: arr_delay <dbl>,
## # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
Anti-joins são úteis na identificação de falta de correspondência. Por exemplo, conectando flights e planes você pode se interessar em saber que existem muitos vôos que não tem correspondência em planes.
flights %>%
anti_join(planes, by = "tailnum") %>%
count(tailnum, sort = TRUE)
## # A tibble: 722 x 2
## tailnum n
## <chr> <int>
## 1 <NA> 2512
## 2 N725MQ 575
## 3 N722MQ 513
## 4 N723MQ 507
## 5 N713MQ 483
## 6 N735MQ 396
## 7 N0EGMQ 371
## 8 N534MQ 364
## 9 N542MQ 363
## 10 N531MQ 349
## # ... with 712 more rows
1 - Qual o siginificado de um vôo ter um tailnum faltante? O que os tail numbers que não tem uma correspondência em planes tem em comum?(dica: uma variável explica ~90% dos problemas.)
2 - Filtre flights para mostrar mostrar apenas os vôos com aviões que tenham feito pelo menos 100 vôos.
3 - Combine fueleconomy::vehicles e fueleconomy::common para encontrar apenas os registros dos modelos mais comuns.
4 - Encontre as 48 horas( no decorrer de um ano inteiro) que tem os piores atrasos. Faça a referência cruzada com os dados de weather. Consegue ver os padrões?
5 - O que anti_join(flights, airports, by = c(“dest” = “faa”)) te diz? O que anti_join(airports, flights, by = c(“faa” = “dest”)) te diz?
6 - Você pode esperar que haja uma relação implicita entre avião e linha aerea, poque cada avião voa por uma unica linha aerea. Confirme ou rejeite esta hipótese usando as ferramentas que você aprendeu até agora.
Os dados com que temos trabalhado ate agora foram preparados para que você tivesse a menor quantidade possível de problemas até agora. Seus próprios dados ou tabelas provavelmente não vão estar do mesmo modo, então aqui vão algumas dicas que você deve aplicar a suas próprias tabelas para fazer com que seus joins funcionem perfeitamente.
1 - Comece identificando as variáveis que formam as chaves primárias em cada tabela. Você normalmente deve fazer isso baseado em seus conhecimentos sobre os dados, não empiricamente olhando combinaçoes de dados que dão um identificador único. Se você olhar para as variáveis sem pensar em seu significado, talvez não dê sorte e encontre combinações que são únicas em sua tabela mas a relação não é verdadeira em geral.
Por exemplo, a altitude e a longitude identifica unicamente cada aeroporto mão não são bons identificadores.
airports %>% count(alt, lon) %>% filter(n > 1)
## # A tibble: 0 x 3
## # ... with 3 variables: alt <dbl>, lon <dbl>, n <int>
2 - Verifique se nenhuma das variáveis na chave primária está faltando. Se algum valor estiver faltando não há como identificar uma observação.
3 - Verifique se suas foreign keys correspondem chaves primárias em outra tabela. O melhor modo de fazer isso é com um anti_join() . è comum que chaves não tenham correspondência por conta de erros de entrada.
Se você tem chaves faltantes, você analisar de forma cuidadosa o uso de inner joins vs. outer joins, considerando cuidadosamente se você quer ou não linhas que não tem correspondência.
Tenha conciência de que apenas checar o número de colunas antes e depois dos joins não é o suficiente para assegurar que o join deu certo. Se você tiver um inner join com chaves duplicadas em ambas as tabelas, você pode não dar sorte e o número de linhas descartadas ser igual ao número de linhas iguais.
São úteis quando se quer quebrar um filtro mais complexo em partes menores. Todas estas operações funcionam com uma linha completa, comparando o valor de cada variável. Elas esperam que as entradas de x e y tenham a mesma variável, e tratam as observações como conjuntos:
#x
#> # A tibble: 3 x 2
#> x y
#> <chr> <chr>
#> 1 1 a
#> 2 1 b
#> 3 2 a
#y
#> # A tibble: 2 x 2
#> x y
#> <chr> <chr>
#> 1 1 a
#> 2 2 b
#intersect(x, y)
#> # A tibble: 1 x 2
#> x y
#> <chr> <chr>
#> 1 1 a
#union(x, y)
#> # A tibble: 4 x 2
#> x y
#> <chr> <chr>
#> 1 2 b
#> 2 2 a
#> 3 1 b
#> 4 1 a
#union_all(x, y)
#> # A tibble: 5 x 2
#> x y
#> <chr> <chr>
#> 1 1 a
#> 2 1 b
#> 3 2 a
#> 4 1 a
#> 5 2 b
#setdiff(x, y)
#> # A tibble: 2 x 2
#> x y
#> <chr> <chr>
#> 1 1 b
#> 2 2 a